// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UserManagementBackstageViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the <seealso cref="UserManagementBackstageViewModel" /> type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Client.Modules.Core.Management.ViewModel
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Windows.Input;
    using System.Windows.Media;

    using Hisaab.Business.Interfaces;
    using Hisaab.Client.Common.BaseClasses;
    using Hisaab.Client.Common.Services;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.ServiceLocation;

    /// <summary>
    /// Defines the <seealso cref="UserManagementBackstageViewModel"/> type.
    /// </summary>
    public class UserManagementBackstageViewModel : ViewModelBase
    {
        /// <summary>
        /// Member variable _userManager
        /// </summary>
        private readonly IUserManager _userManager;

        /// <summary>
        /// Member variable _session
        /// </summary>
        private readonly ISession _session;

        /// <summary>
        /// Member variable _oldPassword
        /// </summary>
        private string _oldPassword;

        /// <summary>
        /// Member variable _newPassword
        /// </summary>
        private string _newPassword;

        /// <summary>
        /// Member variable _confirmPassword
        /// </summary>
        private string _confirmPassword;

        /// <summary>
        /// Member variable _message
        /// </summary>
        private string _message;

        /// <summary>
        /// Member variable _messageColor
        /// </summary>
        private Brush _messageColor;

        /// <summary>
        /// Member variable _secretQuestion
        /// </summary>
        private string _secretQuestion;

        /// <summary>
        /// Member variable _secretAnswer
        /// </summary>
        private string _secretAnswer;

        /// <summary>
        /// Member variable _changePasswordCommand
        /// </summary>
        private DelegateCommand _changePasswordCommand;

        /// <summary>
        /// Member variable _updateSecretQuestionCommand
        /// </summary>
        private DelegateCommand _updateSecretQuestionCommand;

        /// <summary>
        /// Initializes a new instance of the <see cref="UserManagementBackstageViewModel"/> class.
        /// </summary>
        public UserManagementBackstageViewModel()
            : this(ServiceLocator.Current.GetInstance<IUserManager>(), ServiceLocator.Current.GetInstance<ISession>())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UserManagementBackstageViewModel"/> class.
        /// </summary>
        /// <param name="userManager">The user manager.</param>
        /// <param name="session">The session.</param>
        public UserManagementBackstageViewModel(IUserManager userManager, ISession session)
        {
            Contract.Requires<ArgumentNullException>(userManager != null);
            Contract.Requires<ArgumentNullException>(session != null);

            _userManager = userManager;
            _session = session;

            MessageColor = Brushes.Green;

            SecretQuestion = _userManager.GetSecretQuestion(_session.LoggedUser);
        }

        /// <summary>
        /// Gets UpdateCommand.
        /// </summary>
        public ICommand ChangePasswordCommand
        {
            get
            {
                if (_changePasswordCommand == null)
                {
                    _changePasswordCommand = new DelegateCommand(OnChangePassword, CanChangePassword);
                }

                return _changePasswordCommand;
            }
        }

        /// <summary>
        /// Gets the update secret question command.
        /// </summary>
        public ICommand UpdateSecretQuestionCommand
        {
            get
            {
                if (_updateSecretQuestionCommand == null)
                {
                    _updateSecretQuestionCommand = new DelegateCommand(UpdateSecretQuestion, CanUpdateSecretQuestion);
                }

                return _updateSecretQuestionCommand;
            }
        }

        /// <summary>
        /// Gets or sets the old password.
        /// </summary>
        /// <value>
        /// The old password.
        /// </value>
        public string OldPassword
        {
            get
            {
                return _oldPassword;
            }

            set
            {
                RaisePropertyChangingEvent("OldPassword");
                _oldPassword = value;
                RaisePropertyChangedEvent("OldPassword");
            }
        }

        /// <summary>
        /// Gets or sets the new password.
        /// </summary>
        /// <value>
        /// The new password.
        /// </value>
        public string NewPassword
        {
            get
            {
                return _newPassword;
            }

            set
            {
                RaisePropertyChangingEvent("NewPassword");
                _newPassword = value;
                RaisePropertyChangedEvent("NewPassword");
            }
        }

        /// <summary>
        /// Gets or sets the confirm password.
        /// </summary>
        /// <value>
        /// The confirm password.
        /// </value>
        public string ConfirmPassword
        {
            get
            {
                return _confirmPassword;
            }

            set
            {
                RaisePropertyChangingEvent("ConfirmPassword");
                _confirmPassword = value;
                RaisePropertyChangedEvent("ConfirmPassword");
            }
        }

        /// <summary>
        /// Gets or sets the secret question.
        /// </summary>
        /// <value>
        /// The secret question.
        /// </value>
        public string SecretQuestion
        {
            get
            {
                return _secretQuestion;
            }

            set
            {
                RaisePropertyChangingEvent("SecretQuestion");
                _secretQuestion = value;
                RaisePropertyChangedEvent("SecretQuestion");
            }
        }

        /// <summary>
        /// Gets or sets the secret answer.
        /// </summary>
        /// <value>
        /// The secret answer.
        /// </value>
        public string SecretAnswer
        {
            get
            {
                return _secretAnswer;
            }

            set
            {
                RaisePropertyChangingEvent("SecretAnswer");
                _secretAnswer = value;
                RaisePropertyChangedEvent("SecretAnswer");
            }
        }

        /// <summary>
        /// Gets or sets the message.
        /// </summary>
        /// <value>
        /// The message.
        /// </value>
        public string Message
        {
            get
            {
                return _message;
            }

            set
            {
                RaisePropertyChangingEvent("Message");
                _message = value;
                RaisePropertyChangedEvent("Message");
            }
        }

        /// <summary>
        /// Gets or sets the color of the message.
        /// </summary>
        /// <value>
        /// The color of the message.
        /// </value>
        public Brush MessageColor
        {
            get
            {
                return _messageColor;
            }

            set
            {
                RaisePropertyChangingEvent("MessageColor");
                _messageColor = value;
                RaisePropertyChangedEvent("MessageColor");
            }
        }

        /// <summary>
        /// Raises the PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The name of the changed property.</param>
        public override void RaisePropertyChangedEvent(string propertyName)
        {
            base.RaisePropertyChangedEvent(propertyName);
            if (_changePasswordCommand != null && (propertyName == "OldPassword" || propertyName == "NewPassword" || propertyName == "ConfirmPassword"))
            {
                _changePasswordCommand.RaiseCanExecuteChanged();
            }

            if (_updateSecretQuestionCommand != null && (propertyName == "SecretQuestion" || propertyName == "SecretAnswer"))
            {
                _updateSecretQuestionCommand.RaiseCanExecuteChanged();
            }
        }

        /// <summary>
        /// Determines whether this instance [can change password].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can change password]; otherwise, <c>false</c>.
        /// </returns>
        private bool CanChangePassword()
        {
            return !string.IsNullOrWhiteSpace(OldPassword) &&
                !string.IsNullOrWhiteSpace(NewPassword) &&
                NewPassword.Equals(ConfirmPassword, StringComparison.InvariantCulture);
        }

        /// <summary>
        /// Called when [change password].
        /// </summary>
        private void OnChangePassword()
        {
            if (_userManager.ChangePassword(_session.LoggedUser, OldPassword, NewPassword, ConfirmPassword))
            {
                Message = "Password changed successfully";
                OldPassword = NewPassword = ConfirmPassword = string.Empty;
                MessageColor = Brushes.Green;
            }
            else
            {
                Message = "Password change failed. Please make sure you specified correct password and provide matching new and confirm passwords";
                MessageColor = Brushes.Red;
            }
        }

        /// <summary>
        /// Determines whether this instance [can update secret question].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can update secret question]; otherwise, <c>false</c>.
        /// </returns>
        private bool CanUpdateSecretQuestion()
        {
            return !string.IsNullOrWhiteSpace(SecretQuestion) && !string.IsNullOrWhiteSpace(SecretAnswer);
        }

        /// <summary>
        /// Updates the secret question.
        /// </summary>
        private void UpdateSecretQuestion()
        {
            if (_userManager.UpdateSecretQuestion(_session.LoggedUser, SecretQuestion, SecretAnswer))
            {
                Message = "Secret question changed successfully";
                MessageColor = Brushes.Green;
            }
            else
            {
                Message = "Error changing secret question";
                MessageColor = Brushes.Red;
            }
        }
    }
}